Use case: User application program in interrupt mode

Use case applicable in HAL2 for both FLASH and NVM.

Important

In HAL1, the FLASH driver provided fixed callbacks without explicit registration due to its stateless design.

HAL2 introduces a FLASH handle and allows users to register callbacks (for example, HAL_FLASH_RegisterProgramCpltCallback) when callback registration is enabled, enabling more modular event handling.

Sequence diagram

User application program in interrupt mode (HAL1)

@startuml
title: User application program in interrupt mode (HAL1)

hide footbox
participant "User Application" as User
participant "Cortex" as Cortex
participant "FLASH" as FLASH
participant "NVIC" as NVIC
participant "HW" as HW

group #snow Initialization
   User -> Cortex : HAL_NVIC_SetPriority(FLASH_IRQn)
   User -> Cortex : HAL_NVIC_EnableIRQ(FLASH_IRQn)
end

group #snow FLASH Unlock
   User -> FLASH : HAL_FLASH_Unlock()
end

group #snow FLASH Programming (Interrupt Mode)
   User -> FLASH : HAL_FLASH_Program_IT(FLASH_TYPEPROGRAM_GRANULARITY, Address, GRANULARITY)
   loop while Address < EndAddress
      HW -> NVIC : Generate FLASH interrupt
      NVIC -> FLASH : FLASH_IRQHandler()
      FLASH -> User : HAL_EndOfOperationCallback()
      alt Program success
         User -> User : Increment Address by offset
         User -> FLASH : HAL_FLASH_Program_IT(...)
      else Program failure
         User -> User : Handle error
      end
   end
end

group #snow FLASH Lock
   User -> FLASH : HAL_FLASH_Lock()
end

@enduml

Code snippet

HAL1

HAL2

uint32_t Address = FLASH_USER_START_ADDR;
const uint32_t QUADWORD[4] = {
  0x12345678, 0x87654321, 0x12344321, 0x56788765
};

/* Unlock the FLASH to enable the FLASH control register access */
HAL_FLASH_Unlock();

/* FLASH interrupt user callback */
void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
{
  /* This variable counts the number of Program/Erase Operations */
  EndofProgram++;
}

while (Address < EndAddress)
{
  EndofProgram = 0;
  status = HAL_FLASH_Program_IT(FLASH_TYPEPROGRAM_QUADWORD, Address, (uint32_t)QUADWORD);
  while (!EndofProgram) { }
  if (status == HAL_OK)
  {
    Address = Address + offset;
  }
}

/* Lock the FLASH to disable the FLASH control register access */
HAL_FLASH_Lock();
hal_flash_handle_t flash_handle;
uint32_t address = FLASH_START_ADDR;

/* FLASH initialization */
HAL_FLASH_Init(&flash_handle, HAL_FLASH);

/* Unlock the FLASH to enable the FLASH control register access */
HAL_FLASH_ITF_Unlock(HAL_FLASH);

#if defined (USE_HAL_FLASH_PROGRAM_BY_ADDR) && (USE_HAL_FLASH_PROGRAM_BY_ADDR == 1U)

#if defined (USE_HAL_FLASH_REGISTER_CALLBACKS) && (USE_HAL_FLASH_REGISTER_CALLBACKS == 1)
HAL_FLASH_RegisterProgramCpltCallback(&flash_handle, ProgramCpltCallback);
#endif /* USE_HAL_FLASH_REGISTER_CALLBACKS */

/* Set the programming mode according to the FLASH granularity */
HAL_FLASH_SetProgrammingMode(&flash_handle, HAL_FLASH_PROGRAM_QUADWORD);

/* Start interrupt programming */
HAL_FLASH_{area}_ProgramByAddr_IT(&flash_handle, address, data_buf, QUADWORD_SIZE_BYTES);

#endif /* USE_HAL_FLASH_PROGRAM_BY_ADDR */

/* Lock the FLASH to disable the FLASH control register access */
HAL_FLASH_ITF_Lock(HAL_FLASH);

/* FLASH deinitialization */
HAL_FLASH_DeInit(&flash_handle);

Key changes

  1. HAL2 uses callback registration (when enabled) instead of relying only on fixed weak callbacks.

  2. HAL2 interrupt programming APIs are handle-based and area-specialized (HAL_FLASH_{area}_ProgramByAddr_IT).

  3. NVIC configuration remains required, but the interrupt handler and completion callback flow are explicit.